package com.smasher.widget.view;

import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.animation.AccelerateDecelerateInterpolator;

import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;


public class ScrollingDigitalAnimation extends AppCompatTextView {

    private static final String PATTERN_TYPE_FULL = "###0";
    private static final String PATTERN_TYPE_DIVISION = "###0.00";
    private static final long DEFAULT_DURATION = 2000;
    public static final String PATTERN_TYPE_STRING = "%1$s %2$s %3$s";

    private BigDecimal numStart = BigDecimal.ZERO;
    private BigDecimal numEnd = BigDecimal.ZERO;


    private boolean isInt = false;  // 是否为整数
    private long duration = DEFAULT_DURATION; // 持续时间

    private String prefixString = ""; // 前缀字符串
    private String postfixString = ""; // 后缀字符串

    private final DecimalFormat decimalFormat;

    public ScrollingDigitalAnimation(Context context) {
        this(context, null);
    }

    public ScrollingDigitalAnimation(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ScrollingDigitalAnimation(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 初始化默认格式化器
        decimalFormat = (DecimalFormat) NumberFormat.getNumberInstance();
        init();
    }

    private void init() {
        decimalFormat.setGroupingUsed(true); // 使用千位分隔符
    }

    // 设置动画持续时间，默认 2000 ms
    public void setDuration(long duration) {
        this.duration = duration;
    }

    public void setNumberString(String number) {
        setNumberString("0", number);
    }

    public void setNumberString(String numberStart, String numberEnd) {
        try {
            this.numStart = new BigDecimal(numberStart);
            this.numEnd = new BigDecimal(numberEnd);
            this.isInt = determineIfInteger(this.numStart, this.numEnd);
            // 数字合法，开始数字的动画
            startAnimation();
        } catch (Exception e) {
            // 数字不合法，直接调用，setText() 设置最终的值
            setText(String.format(PATTERN_TYPE_STRING, prefixString, numberEnd, postfixString));
        }
    }

    private boolean determineIfInteger(BigDecimal numStart, BigDecimal numEnd) {
        return numStart.stripTrailingZeros().scale() <= 0
                && numEnd.stripTrailingZeros().scale() <= 0;
    }

    /**
     * 设置前缀字符串方法
     *
     * @param prefixString prefixString
     */
    public void setPrefixString(String prefixString) {
        this.prefixString = prefixString;
    }

    /**
     * 设置后缀字符串方法
     *
     * @param postfixString postfixString
     */
    public void setPostfixString(String postfixString) {
        this.postfixString = postfixString;
    }

    private void startAnimation() {
        BigDecimalEvaluator evaluator = new BigDecimalEvaluator();
        // 创建数字动画，并设置起始值和最终值
        ValueAnimator valueAnimator = ValueAnimator.ofObject(evaluator, numStart, numEnd);
        valueAnimator.setDuration(duration);
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addUpdateListener(animation -> {
            BigDecimal value = (BigDecimal) animation.getAnimatedValue();
            setText(String.format(PATTERN_TYPE_STRING, prefixString, format(value), postfixString));
        });
        valueAnimator.start();
    }

    /**
     * 格式化 BigDecimal ，小数部分时保留两位小数并四舍五入
     *
     * @param bd bd
     * @return String
     */
    private String format(BigDecimal bd) {
        synchronized (decimalFormat) { // 线程安全
            // 根据是否为整数选择不同的格式化模式
            String pattern = isInt || bd.scale() <= 0 ? PATTERN_TYPE_FULL : PATTERN_TYPE_DIVISION;
            decimalFormat.applyPattern(pattern);
            return prefixString + decimalFormat.format(bd) + postfixString;
        }
    }

    static class BigDecimalEvaluator implements TypeEvaluator<BigDecimal> {
        // 计算线性插值器的结果
        @Override
        public BigDecimal evaluate(float fraction, BigDecimal startValue, BigDecimal endValue) {
            BigDecimal difference = endValue.subtract(startValue);
            return startValue.add(difference.multiply(BigDecimal.valueOf(fraction)));
        }
    }

}
